package org.fastsyncer.parser.redis;

import java.util.List;
import java.util.Map;
import java.util.Queue;

import org.apache.commons.lang.StringUtils;
import org.fastsyncer.common.entity.Mapping;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.common.entity.RedisConfig;
import org.fastsyncer.connector.redis.RedisConnector;
import org.fastsyncer.connector.redis.RedisTemplate;
import org.fastsyncer.connector.util.RedisUtil;
import org.fastsyncer.parser.framework.Parser;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class RedisParser implements Parser {

    private static volatile RedisParser instance = null;

    private RedisParser() {
    }

    public static RedisParser getInstance() {
        if (null == instance) {
            synchronized (RedisParser.class) {
                if (null == instance) {
                    instance = new RedisParser();
                }
            }
        }
        return instance;
    }

    private static Logger logger = LoggerFactory.getLogger(RedisParser.class);

    @Override
    public List<Map<String, Object>> batchQuery(MappingTask mappingTask, Integer startPos, Integer endPos) throws Exception {
        return null;
    }

    @Override
    public Integer[] batchInsert(MappingTask mappingTask, List<Map<String, Object>> rows, Integer[] pos, Queue<JSONObject> reasonQuene) throws Exception {
        // 批量条数
        int size = rows.size();
        // 总数和成功数
        int total = size;
        int success = 0;
        // 1.同步数据源、目标源属性
        Mapping targetMapping = mappingTask.getTargetMapping();
        RedisConfig config = (RedisConfig) targetMapping.getConfig();

        // 2.获取插入redis的key
        String key = config.getKey();
        if (StringUtils.isBlank(key)) {
            throw new NullPointerException("The redis key can't be null.");
        }

        // 3.循环插入key值
        RedisConnector connector = RedisConnector.getInstance();
        RedisTemplate template = null;
        try {
            template = connector.getRedisTemplate(config);
            if (null != template) {
                String k;
                for (Map<String, Object> r : rows) {
                    k = (String) r.get(key);
                    if (null == k) {
                        continue;
                    }
                    // 将map序列化
                    template.set(k.getBytes(), RedisUtil.serializeObj(r));
                    success++;
                }
            }
        } catch (Exception e) {
            try {
                // 记录错误信息
                JSONObject err = new JSONObject();
                if (pos != null && pos.length == 2) {
                    err.put("startPos", pos[0]);
                    err.put("endPos", pos[1]);
                }
                err.put("message", e.getMessage());
                reasonQuene.offer(err);
            } catch (JSONException e1) {
                logger.error("When logging an error message: Converts a JSONObject exception!");
            }
        } finally {
            // 关闭连接
            if (null != template) {
                template.close();
            }
        }
        return new Integer[] { total, success };
    }

    @Override
    public boolean insert(MappingTask mappingTask, Map<String, Object> row) throws Exception {
        // 1.同步数据源、目标源属性
        Mapping targetMapping = mappingTask.getTargetMapping();
        RedisConfig config = (RedisConfig) targetMapping.getConfig();

        // 2.获取插入redis的key
        String key = config.getKey();
        if (StringUtils.isBlank(key)) {
            throw new NullPointerException("The redis key can't be null.");
        }

        // 3.循环插入key值
        RedisConnector connector = RedisConnector.getInstance();
        RedisTemplate template = null;
        boolean res = false;
        try {
            template = connector.getRedisTemplate(config);
            if (null != template) {
                String k = (String) row.get(key);
                if (null == k) {
                    return res;
                }
                // 将map序列化
                template.set(k.getBytes(), RedisUtil.serializeObj(row));
                res = true;
            }
        } catch (Exception e) {
            logger.error("RedisParser invoke insert method throw an exception:" + e.getLocalizedMessage());
        } finally {
            // 关闭连接
            if (null != template) {
                template.close();
            }
        }
        return res;
    }

    @Override
    public boolean update(MappingTask mappingTask, Map<String, Object> row) throws Exception {
        // 1.同步数据源、目标源属性
        Mapping targetMapping = mappingTask.getTargetMapping();
        RedisConfig config = (RedisConfig) targetMapping.getConfig();

        // 2.获取插入redis的key
        String key = config.getKey();
        if (StringUtils.isBlank(key)) {
            throw new NullPointerException("The redis key can't be null.");
        }

        // 3.循环插入key值
        RedisConnector connector = RedisConnector.getInstance();
        RedisTemplate template = null;
        boolean res = false;
        try {
            template = connector.getRedisTemplate(config);
            if (null != template) {
                String k = (String) row.get(key);
                if (null == k) {
                    return res;
                }
                // 将map序列化
                template.set(k.getBytes(), RedisUtil.serializeObj(row));
                res = true;
            }
        } catch (Exception e) {
            logger.error("RedisParser invoke update method throw an exception:" + e.getLocalizedMessage());
        } finally {
            // 关闭连接
            if (null != template) {
                template.close();
            }
        }
        return res;
    }

    @Override
    public boolean delete(MappingTask mappingTask, Map<String, Object> row) throws Exception {
        // 1.同步数据源、目标源属性
        Mapping targetMapping = mappingTask.getTargetMapping();
        RedisConfig config = (RedisConfig) targetMapping.getConfig();

        // 2.获取插入redis的key
        String key = config.getKey();
        if (StringUtils.isBlank(key)) {
            throw new NullPointerException("The redis key can't be null.");
        }

        // 3.循环插入key值
        RedisConnector connector = RedisConnector.getInstance();
        RedisTemplate template = null;
        boolean res = false;
        try {
            template = connector.getRedisTemplate(config);
            if (null != template) {
                String k = (String) row.get(key);
                if (null == k) {
                    return res;
                }
                // 将map序列化
                template.del(k.getBytes());
                res = true;
            }
        } catch (Exception e) {
            logger.error("RedisParser invoke delete method throw an exception:" + e.getLocalizedMessage());
        } finally {
            // 关闭连接
            if (null != template) {
                template.close();
            }
        }
        return res;
    }

}
